//! Upravljanje prekidima - razina jezgre

#define _J_POZIVI_JEZGRE_C_
#include "pozivi_jezgre.h"

#include "tipovi.h"
#include "razno.h"
#include "spremnik.h"
#include "dretve.h"
#include "procesi.h"
#include "ispis.h"
#include <arh/kontekst.h>

//poziva se iz prekidne funkcije
void j_pozivi_jezgre ( int id_prekida, void *parametri )
{
	int id_procesa = j_aktivni_proces ();

	struct {
		//parametri su na stogu dretve u ovom redoslijedu
		int id;
		void *param;
		int *povvr;

	} *param = parametri;

	void *param_za_jf = param->param;

	void *ppovvr = j_puj ( id_procesa, param->povvr );

	if ( param_za_jf != NULL )
		param_za_jf = j_puj ( id_procesa, param_za_jf );

	if ( param->id < 0 || param->id > BROJ_J_FUNKCIJA ) {
		j_ispisi ( "id van granica (%d)", param->id );
	}
	else {
		//ako naknadno treba mijenjati povratnu vrijednost
		//zapisi adresu u opisnik dretve (npr. za cekaj_sinkro_t funkc)
		j_zapisi_adresu_povratne_vrijednosti ( ppovvr );

		int povvr = j_fun[param->id] ( param_za_jf );

		//nema povratka iz:
		//	DRETVA_ZAVRSETAK, KRAJ_OBRADE_DOGADJAJA
		//pa ne stavljati povratnu vrijednost 'negdje'
		if ( param->id != DRETVA_ZAVRSETAK && 
			param->id != KRAJ_OBRADE_DOGADJAJA )

			*( (int *) ppovvr ) = povvr;
	}
}


//implementacije - par primjera

int funkcija1 (void *x)
{
	//povecava vrijednost za 1 (pretpostavlja int *)
	int *p = x;
	
	PARAMNULL(p);
	
	*p += 1;

	return 7;
}

int funkcija2 (void *x)
{
	//racuna duljinu teksta (pretpostavlja char *)
	int i;
	char *c = x;
	
	PARAMNULL(c);

	for (i = 0; c[i] != 0; i++)
		;

	return i + 1;
}

int funkcija3 (void *x)
{
	//trazi najmanji broj (pretpostavlja pointer na {int, double[]})
	int *np = x;
	double *p;
	int n, i, min = -1;
	
	PARAMNULL(np);

	n = *np;
	np++;
	p = (double *) np;

	if (n > 0) {
		min = 0;

		for (i = 1; i < n; i++)
			if (p[i] < p[min])
				min = i;
	}
	
	return min;
}
